// 更新vnode
// 更新dom

import { updateFragmentComponent, updateFunctionComponent, updateHostComponent } from "./reconciler"
import { shouldYield, scheduleCallback } from "./scheduler"
import { isFn, isStr, Placement, updateNode, Update } from "./utils"


// 当前正在工作中的 fiber
let wipRoot = null
let nextUnitOfWork = null
export function scheduleUpdateOnFiber(fiber) {
  fiber.alternate = {...fiber}
  wipRoot = fiber
  nextUnitOfWork = wipRoot
  scheduleCallback(workLoop);
}


// 更新当前fiber
// 返回下一个要更新的fiber
function performUnitOfWork(wip) {
  const {type} = wip
  if(isStr(type)) {
    updateHostComponent(wip)
  }else if(isFn(type)) {
    updateFunctionComponent(wip)
  }else{
    updateFragmentComponent(wip)
  }
  // 深度优先
  if(wip.child) {
    return wip.child
  }
  while(wip) {
    if(wip.sibling) {
      return wip.sibling
    }
    wip = wip.return
  }
  
  return null
}


function workLoop() {
  // console.log('空间时间',idleDeadline.timeRemaining())
  // 有下个fiber 并且 空闲时间有
  // while(nextUnitOfWork && !shouldYield()) {
  while(nextUnitOfWork) {
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
  }
  // fiber没了  那就更新dom了
  if(!nextUnitOfWork && wipRoot) {
    // 
    commitRoot()
  }
}


function commitRoot() {
  // 函数组价冲自己开始提交
  if(isFn(wipRoot.type)) {
    commitWorker(wipRoot)
    return
  }
  commitWorker(wipRoot.child)
}

function invokeHooks(wip) {
  const {updateQueueOfEffect, updateQueueOfLayoutEffect} = wip
  for (let i = 0; i < updateQueueOfLayoutEffect.length; i++) {
    const effect = updateQueueOfLayoutEffect[i];
    effect.create()
  }
  for (let i = 0; i < updateQueueOfEffect.length; i++) {
    const effect = updateQueueOfEffect[i];
    scheduleCallback(()=>{
      effect.create()
    })
  }
}

function commitWorker(wip) {
  if (!wip) {
    return;
  }
  if (isFn(wip.type)) {
    invokeHooks(wip);
  }
  // 1. commit自己
  const {flags, stateNode} = wip;
  // 父dom节点
  let parentNode = getParentNode(wip.return); //wip.return.stateNode;

  // if (flags & Placement && stateNode) {
  //   parentNode.appendChild(stateNode);
  // }

  // 插入
  if (flags & Placement && stateNode) {
    let hasSiblingNode = foundSiblingNode(wip, parentNode);
    if (hasSiblingNode) {
      parentNode.insertBefore(stateNode, hasSiblingNode);
    } else {
      parentNode.appendChild(wip.stateNode);
    }
  }

  if (flags & Update && stateNode) {
    updateNode(stateNode, wip.alternate.props, wip.props);
  }

  // 检查wip有没有要删除的子节点
  if (wip.deletions) {
    commitDeletions(wip.deletions, stateNode || parentNode);
    wip.deletions = null;
  }

  // 2. commit child
  commitWorker(wip.child);
  // 3. commit sibling
  commitWorker(wip.sibling);
}
// 找后面最近的有dom节点的fiber
function foundSiblingNode(fiber, parentNode) {
  let siblingHasNode = fiber.sibling;
  let node = null;
  while (siblingHasNode) {
    node = siblingHasNode.stateNode;
    if (node && parentNode.contains(node)) {
      return node;
    }
    siblingHasNode = siblingHasNode.sibling;
  }

  return null;
}

function commitDeletions(deletions, parentNode) {
  for (let i = 0; i < deletions.length; i++) {
    const element = deletions[i];
    parentNode.removeChild(getStateNode(element));
  }
}

function getParentNode(wip) {
  while (wip) {
    if (wip.stateNode) {
      return wip.stateNode;
    }
    wip = wip.return;
  }
}


function getStateNode(fiber) {
  while (!fiber.stateNode) {
    fiber = fiber.child;
  }

  return fiber.stateNode;
}

// 调度的概念
// requestIdleCallback(workLoop)
// scheduleCallback(workLoop)